/**
  ******************************************************************************
  * @file    BSP_adc.c
  * @author  Silan - MC Team
  * @version 1.0.0
  * @date    2017/07/19
  * @brief   ADC related Configuration Source File
  * @details None
  * @note    None
  ******************************************************************************
  * @attention
  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
  * AS A RESULT, SILAN MICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
  * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
  * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  ******************************************************************************
  * Change History
  * -# 2017/07/19 | v1.0.0 | Wangjianlong | Creat file.
  *
  ******************************************************************************
  */

/*******************************************************************************
 * Include file
 ******************************************************************************/
#include "SC32F58128.h"
#include "BSP_adc.h"
#include "DrvParamCommon.h"

/*******************************************************************************
 * Global data for the project
 ******************************************************************************/
union ADSMP g_uAdSmp;// __attribute__ ((at(0x20003480)));

/*******************************************************************************
 * Loacal data for the current file
 ******************************************************************************/

/*******************************************************************************
 * Local prototypes function
 ******************************************************************************/

/*******************************************************************************
 * Loacal function for the current file
 ******************************************************************************/

/*******************************************************************************
 * Global function for the current project
 ******************************************************************************/

/**
  * @brief  get sampled data.
  */
#pragma arm section code = "RAMCODE"
uint8_t GetSmpData(enum ADC_SMP_GROUP_e Num)
{
  uint8_t   i;
  uint16_t  u16DlyCnt;
  uint32_t* pSrcAd;
  uint32_t* pDstAd;
  uint32_t  u32Msk;

  switch(Num){
    case ADC_SMP_GRP_PMSM:{
      pSrcAd = (uint32_t *)&(ADC->ADCRESULT0);
      pDstAd = (uint32_t *)&g_uAdSmp;
      u32Msk = (1uL<<PMSM_AD_CHNL) - 1;
      while(ADC->ADCSOCFLG1&u32Msk);
      for(i = 0; i < PMSM_AD_CHNL; i++){
        *pDstAd = *(volatile uint32_t*)(pSrcAd);
        pSrcAd++;
        pDstAd++;
      }
      break;
    }

    case ADC_SMP_GRP_FAN:{
      pSrcAd = (uint32_t *)&(ADC->ADCRESULT0) + PMSM_AD_CHNL;
      pDstAd = (uint32_t *)&g_uAdSmp + PMSM_AD_CHNL;
      u32Msk = ((1<<FAN_AD_CHNL)-1) << PMSM_AD_CHNL;
      while(ADC->ADCSOCFLG1&u32Msk);
      for(i = 0; i < FAN_AD_CHNL; i++){
        *pDstAd = *(volatile uint32_t*)(pSrcAd);
        pSrcAd++;
        pDstAd++;
      }
      break;
    }

    case ADC_SMP_GRP_PFC:{
      pSrcAd = (uint32_t *)&(ADC->ADCRESULT0) + PMSM_AD_CHNL + FAN_AD_CHNL;
      pDstAd = (uint32_t *)&g_uAdSmp + PMSM_AD_CHNL + FAN_AD_CHNL;
      u32Msk = ((1<<(PFC_AD_CHNL-1))-1) << (PMSM_AD_CHNL+FAN_AD_CHNL);
      while(ADC->ADCSOCFLG1&u32Msk);
      for(i = 0; i < (PFC_AD_CHNL-1); i++){
        *pDstAd = *(volatile uint32_t*)(pSrcAd);
        pSrcAd++;
        pDstAd++;
      }
      break;
    }

    case ADC_SMP_GRP_AC:{
      pSrcAd = (uint32_t *)&(ADC->ADCRESULT0) + PMSM_AD_CHNL + PFC_AD_CHNL + FAN_AD_CHNL;
      pDstAd = (uint32_t *)&g_uAdSmp + PMSM_AD_CHNL + PFC_AD_CHNL + FAN_AD_CHNL;
      u32Msk = ((1<<(AC_CTRL_AD_CHNL-1))-1) << (PMSM_AD_CHNL+PFC_AD_CHNL+FAN_AD_CHNL);
      while(ADC->ADCSOCFLG1&u32Msk);
      for(i = 0; i < (AC_CTRL_AD_CHNL-1); i++){
        *pDstAd = *(volatile uint32_t*)(pSrcAd);
        pSrcAd++;
        pDstAd++;
      }
      break;
    }

    default:
      break;
  }

  return 0;
}
#pragma arm section

/**
  * @brief  ADC Initialization.
  */
void BSP_AdcConfig(void)
{
  uint8_t u8cnt = 0;
  uint32_t u32Tmp;

  AdcInit(ADC_50V,ADC_CLKDIV_3);  // ADC Voltage = 5.0V, Clock Division = 3
  ACCESS_ENABLE;
  ADC->ADCCTL2_b.NONOVERLAP = 0;  // Overlap enable
  ADC->ADCCTL2_b.dlyprediv = 1;   // Trigger delay clock prescale: SystemMtClock/2
  ACCESS_DISABLE;

  g_sAdcSoc[0].AdcSocCtl.bit.ChnlSel  = ADCSOC0_CHNL ;  //
  g_sAdcSoc[1].AdcSocCtl.bit.ChnlSel  = ADCSOC1_CHNL ;  //
  g_sAdcSoc[2].AdcSocCtl.bit.ChnlSel  = ADCSOC2_CHNL ;  //

  if(g_sFanDrvParam.u8SingleShuntEn){
    g_sAdcSoc[3].AdcSocCtl.bit.ChnlSel  = ADCSOC3_CHNL ;  //
    g_sAdcSoc[4].AdcSocCtl.bit.ChnlSel  = ADCSOC3_CHNL ;  //
    g_sAdcSoc[5].AdcSocCtl.bit.ChnlSel  = ADCSOC3_CHNL ;  //
  }else{
    g_sAdcSoc[3].AdcSocCtl.bit.ChnlSel  = ADCSOC3_CHNL ;  //
    g_sAdcSoc[4].AdcSocCtl.bit.ChnlSel  = ADCSOC4_CHNL ;  //
    g_sAdcSoc[5].AdcSocCtl.bit.ChnlSel  = ADCSOC5_CHNL ;  //
  }

  g_sAdcSoc[6].AdcSocCtl.bit.ChnlSel  = ADCSOC6_CHNL ;  //
  g_sAdcSoc[7].AdcSocCtl.bit.ChnlSel  = ADCSOC7_CHNL ;  //
  g_sAdcSoc[8].AdcSocCtl.bit.ChnlSel  = ADCSOC8_CHNL ;  //
  g_sAdcSoc[9].AdcSocCtl.bit.ChnlSel  = ADCSOC9_CHNL ;  //
  g_sAdcSoc[10].AdcSocCtl.bit.ChnlSel = ADCSOC10_CHNL;  //
  g_sAdcSoc[11].AdcSocCtl.bit.ChnlSel = ADCSOC11_CHNL;  //
  g_sAdcSoc[12].AdcSocCtl.bit.ChnlSel = ADCSOC12_CHNL;  //
  g_sAdcSoc[13].AdcSocCtl.bit.ChnlSel = ADCSOC13_CHNL;  //
  g_sAdcSoc[14].AdcSocCtl.bit.ChnlSel = ADCSOC14_CHNL;  //
  g_sAdcSoc[15].AdcSocCtl.bit.ChnlSel = ADCSOC15_CHNL;  //

  g_sAdcSoc[0].AdcSocCtl.bit.TrigSel  = TRG_PWM0SOCA;
  g_sAdcSoc[1].AdcSocCtl.bit.TrigSel  = TRG_PWM1SOCA;
  g_sAdcSoc[2].AdcSocCtl.bit.TrigSel  = TRG_PWM2SOCA;
  g_sAdcSoc[3].AdcSocCtl.bit.TrigSel  = TRG_PWM3SOCA;
  if(g_sFanDrvParam.u8SingleShuntEn){
    g_sAdcSoc[4].AdcSocCtl.bit.TrigSel  = TRG_PWM6SOCA;
    g_sAdcSoc[5].AdcSocCtl.bit.TrigSel  = TRG_PWM6SOCB;
  }else{
    g_sAdcSoc[4].AdcSocCtl.bit.TrigSel  = TRG_PWM4SOCA;
    g_sAdcSoc[5].AdcSocCtl.bit.TrigSel  = TRG_PWM5SOCA;
  }
  g_sAdcSoc[6].AdcSocCtl.bit.TrigSel  = TRG_PWM7SOCA;
  g_sAdcSoc[7].AdcSocCtl.bit.TrigSel  = TRG_PWM7SOCA;
  g_sAdcSoc[8].AdcSocCtl.bit.TrigSel  = TRG_PWM7SOCA;
  g_sAdcSoc[9].AdcSocCtl.bit.TrigSel  = TRG_PWM7SOCB;
  g_sAdcSoc[10].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;
  g_sAdcSoc[11].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;
  g_sAdcSoc[12].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;
  g_sAdcSoc[13].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;
  g_sAdcSoc[14].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;
  g_sAdcSoc[15].AdcSocCtl.bit.TrigSel = TRG_PWM0SOCB;

  g_sAdcSoc[0].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[1].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[2].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[3].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[4].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[5].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[6].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[7].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[8].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[9].AdcSocCtl.bit.SmpSel  = 8;
  g_sAdcSoc[10].AdcSocCtl.bit.SmpSel = 8;
  g_sAdcSoc[11].AdcSocCtl.bit.SmpSel = 8;
  g_sAdcSoc[12].AdcSocCtl.bit.SmpSel = 8;
  g_sAdcSoc[13].AdcSocCtl.bit.SmpSel = 8;
  g_sAdcSoc[14].AdcSocCtl.bit.SmpSel = 8;
  g_sAdcSoc[15].AdcSocCtl.bit.SmpSel = 8;

  u32Tmp = g_sPmsmDrvParam.fSmpDelay * (SystemMtClock / 1000000) / 2;
  if(g_sPmsmDrvParam.u8SingleShuntEn){
    g_sAdcSoc[0].AdcSocCtl.bit.DlySel  = u32Tmp;
    g_sAdcSoc[1].AdcSocCtl.bit.DlySel  = u32Tmp;
    g_sAdcSoc[2].AdcSocCtl.bit.DlySel  = u32Tmp;
  }else{
    g_sAdcSoc[0].AdcSocCtl.bit.DlySel  = 0;
    g_sAdcSoc[1].AdcSocCtl.bit.DlySel  = 0;
    g_sAdcSoc[2].AdcSocCtl.bit.DlySel  = 0;
  }

  u32Tmp = g_sFanDrvParam.fSmpDly * (SystemMtClock / 1000000) / 2;
  if(g_sFanDrvParam.u8SingleShuntEn){
    g_sAdcSoc[3].AdcSocCtl.bit.DlySel = u32Tmp;
  }else{
    g_sAdcSoc[3].AdcSocCtl.bit.DlySel = 0x0;
  }

  g_sAdcSoc[0].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[1].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[2].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[3].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[4].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[5].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[6].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[7].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[8].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[9].AdcSocCtl.bit.HighPriority  = 1;
  g_sAdcSoc[10].AdcSocCtl.bit.HighPriority = 0;
  g_sAdcSoc[11].AdcSocCtl.bit.HighPriority = 0;
  g_sAdcSoc[12].AdcSocCtl.bit.HighPriority = 0;
  g_sAdcSoc[13].AdcSocCtl.bit.HighPriority = 0;
  g_sAdcSoc[14].AdcSocCtl.bit.HighPriority = 0;
  g_sAdcSoc[15].AdcSocCtl.bit.HighPriority = 0;

  u32Tmp = PMSM_AD_CHNL + FAN_AD_CHNL + PFC_AD_CHNL - 3;
  g_sAdcSoc[u32Tmp].AdcIntCtl.bit.AdcIntNum = ADC_INT2;  // ADCINT is triggered by the penultimate EOC of PFC control
  g_sAdcSoc[u32Tmp].AdcIntCtl.bit.AdcIntEn = 1;
  g_sAdcSoc[14].AdcIntCtl.bit.AdcIntNum = ADC_INT4; // ADCINT4 is triggered by EOC14(A/C control)
  g_sAdcSoc[14].AdcIntCtl.bit.AdcIntEn = 1;

  /* VDC limit protect */
  u32Tmp += 1;
  g_sAdcSoc[u32Tmp].AdcIntCtl.bit.AdcCmpSrcCfgEn = 1;    // ADC comparator source select register congif enable
  g_sAdcSoc[u32Tmp].AdcIntCtl.bit.AdcCmpChnl = 0;        // ADC comparator 0 is selected.
  g_sAdcSoc[u32Tmp].AdcIntCtl.bit.AdcCmpHiIntEn = 1;     // ADC comparator interrupted(select channel) enable.
  g_sAdcSoc[u32Tmp].u16CompHigh = _IQ12(2.0*g_sPfcDrvParam.u8VdcOVLVal4Peak/g_sPfcDrvParam.u16PfcMaxVdc);

  for(u8cnt = 0; u8cnt < 16; u8cnt++){
    AdcSocConfig(u8cnt,&g_sAdcSoc[u8cnt]);
  }
}

/*---------------------------------- End of the file ---------------------------------*/
